home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / pbq.zip / PBQ.C < prev    next >
C/C++ Source or Header  |  1991-09-21  |  11KB  |  409 lines

  1. /*******************************************************************\
  2. *                                                                   *
  3. * PBQ - Pacsat Broadcast Queue/Query Purge                          *
  4. *                                                                   *
  5. * This program helps you purge the directory of partially-received  *
  6. * files generated by PB.  For each partial file in the directory,   *
  7. * PBQ tells you everything it can figure out about the file.  It    *
  8. * then asks what you want to do with the file.  If you wish to      *
  9. * continue receiving the file, PBQ does nothing.  If you wish to    *
  10. * delete the partial files for now, PBQ deletes the files for you.  *
  11. * If you wish to ignore that file number forever, PBQ deletes the   *
  12. * partial files and creates a dummy .DL file (0 bytes long) so      *
  13. * that PB won't ever try to receive that file again.                *
  14. *                                                                   *
  15. * Compiled with Microsoft C 6.00AX:                                 *
  16. *      cl -W3 pbq.c                                                 *
  17. *                                                                   *
  18. \*******************************************************************/
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <time.h>
  24. #include <dos.h>
  25. #include <errno.h>
  26. #include <graph.h>
  27. #include <conio.h>
  28.  
  29. #include "dirlist.h"
  30.  
  31. int    main(void);
  32. void    init_directory(void);
  33. void    process_partial_file(char *holname);
  34. unsigned long    summarize_dir_info(unsigned long file_number);
  35. void    print_entry(dir_entry entry);
  36. void    summarize_hole_file(char *holname, unsigned long file_length);
  37. void    end_pbq(void);
  38. void    hitanykey(void);
  39. int    get_option(char *opts);
  40. int    delete_files(char *holname, char *actname);
  41.  
  42.     /* The PG.DIR directory file.  Opened and initially scanned by
  43.      * one routine, then indexed-read by another.  */
  44.  
  45. FILE    *dirfile = NULL;
  46.  
  47.  
  48. #define    DIRMAX    1000
  49. struct findex_entry            /* Index to the directory file */
  50.     {
  51.     unsigned long    fileno;
  52.     unsigned long    offset;
  53.     }    findex[DIRMAX];
  54.  
  55. int    number_of_entries;
  56.  
  57.             /* Show a length as BAD_LENGTH if we don't really know it */
  58. #define    BAD_LENGTH    (0xFFFFFFFF)
  59.  
  60.             /* Keep a few statistics */
  61. int    files_kept = 0;
  62. int    files_deleted = 0;
  63. int    files_faked = 0;
  64.  
  65. int main(void)
  66. {
  67. struct find_t fileinfo;
  68.  
  69. _clearscreen(_GCLEARSCREEN);            /* clear the entire screen */
  70.  
  71. printf("PBQ - Pacsat Broadcast Queue/Query Purge 1.0\n");
  72. printf("Copyright 1991 Paul Williamson, KB5MU\n\n");
  73.  
  74. _settextwindow(4, 1, 25, 80);            /* All per-file output fits in here */
  75.  
  76.                                         /* Get rid of the old hole files */
  77. if (_dos_findfirst("*.OLH", _A_NORMAL, &fileinfo) == 0)
  78.     do {
  79.         remove(fileinfo.name);
  80.         }
  81.     while (_dos_findnext(&fileinfo) == 0);
  82.  
  83.                     /* Now ask about each partially received file */
  84. if (_dos_findfirst("*.HOL", _A_NORMAL, &fileinfo) != 0)
  85.     {
  86.     printf("No partially downloaded files exist.\n");
  87.     exit(1);
  88.     }
  89.  
  90. init_directory();    /* Go get the directory info so we can look up fast */
  91.  
  92.                     /* Now scan thru all the partial files and do our thing */
  93. do {
  94.     process_partial_file(fileinfo.name);
  95.     }
  96. while (_dos_findnext(&fileinfo) == 0);
  97.  
  98. end_pbq();        /* Report a few statistics and exit */
  99.  
  100. return 0;
  101. }
  102.  
  103. void end_pbq(void)
  104. {
  105. _clearscreen(_GWINDOW);
  106. _settextposition(14, 10);
  107. printf("<C>ontinued: %d", files_kept);
  108. _settextposition(15, 10);
  109. printf("<D>eleted:   %d", files_deleted);
  110. _settextposition(16, 10);
  111. printf("<F>aked out: %d", files_faked);
  112.  
  113. _settextposition(20, 10);
  114. exit(0);
  115. }
  116.  
  117. /*******************************************************\
  118. *                                                       *
  119. * init_directory                                        *
  120. * Open PG.DIR, and scan through it once and record the  *
  121. * fseek cookie for each file number.                    *
  122. *                                                       *
  123. \*******************************************************/
  124.  
  125. void    init_directory(void)
  126. {
  127. int            i;
  128. dir_entry    entry;
  129.  
  130. if ((dirfile = fopen("PG.DIR", "rb")) == NULL)
  131.     {
  132.     printf("Can't open PG.DIR.\n");
  133.     return;
  134.     }
  135.  
  136. i = 0;
  137. findex[i].offset = ftell(dirfile);
  138. while (!feof(dirfile) && !ferror(dirfile))
  139.     {
  140.     if (!fread((void *) &entry, sizeof entry, (size_t) 1, dirfile))
  141.         {
  142.         if (ferror(dirfile))
  143.             {
  144.             printf("Error reading PG.DIR.\n");
  145.             exit(1);
  146.             }
  147.         }
  148.     else
  149.         {
  150.         findex[i].fileno = entry.fileno;
  151. //printf("Dir entry %lx at %lx\n", findex[i].fileno, findex[i].offset); //debug
  152.         if (++i >= DIRMAX)                /* don't overrun the array */
  153.             break;
  154.         findex[i].offset = ftell(dirfile);    /* cookie points to next entry */
  155.         }
  156.     }
  157.  
  158. number_of_entries = i-1;
  159. }
  160.  
  161. /**********************************************************\
  162. *                                                          *
  163. * process_partial_file                                     *
  164. *                                                          *
  165. * This routine is called for each partially received file  *
  166. * in the directory.  It displays whatever information it   *
  167. * can find, and then asks the user what to do.             *
  168. *                                                          *
  169. \**********************************************************/
  170.  
  171. void process_partial_file(char *holname)
  172. {
  173. char    rootname[13];
  174. char    actname[13];
  175. unsigned long    fileno;
  176. unsigned long    filelen;
  177. FILE    *fakefile;
  178.  
  179. _clearscreen(_GWINDOW);                    /* Clear away old per-file info */
  180. _settextposition(4, 1);
  181.  
  182.                                                 /* Play with the filenames a bit */
  183. strcpy(rootname, holname);
  184. *strchr(rootname, '.') = '\0';        /* trim off the extension */
  185. strcpy(actname, rootname);
  186. strcat(actname, ".ACT");
  187. if (sscanf(holname, "%lx.HOL", &fileno) != 1)
  188.     {
  189.     printf("What's this?  A non-numeric filename (%s)?  Ignored.\n",
  190.                 rootname);
  191.     return;
  192.     }
  193.  
  194. printf("File Number: %s\n", rootname);
  195. filelen = summarize_dir_info(fileno);
  196. summarize_hole_file(holname, filelen);
  197.  
  198. _settextposition(14, 10);
  199. printf("<C>ontinue to receive this file (PBQ does nothing)");
  200. _settextposition(15, 10);
  201. printf("<D>elete this partially received file");
  202. _settextposition(16, 10);
  203. printf("<F>ake out PB with a dummy .DL file");
  204. _settextposition(17, 10);
  205. printf("<Q>uit PBQ");
  206. _settextposition(19, 10);
  207. printf("C D F Q : ");
  208.  
  209. switch(get_option("CDFQ"))
  210.     {
  211.     case 'C':
  212.         files_kept++;
  213.         break;
  214.  
  215.     case 'F':
  216.         strcat(rootname, ".DL");
  217.         if ((fakefile = fopen(rootname, "w")) == NULL)
  218.             {
  219.             printf("\nCouldn't create fake .DL file!\n");
  220.             hitanykey();
  221.             }
  222.         else
  223.             {
  224.             files_faked++;
  225.             delete_files(holname, actname);
  226.             fclose(fakefile);
  227.             }
  228.         break;    
  229.  
  230.     case 'D':
  231.         if (delete_files(holname, actname))
  232.             files_deleted++;
  233.         break;
  234.             
  235.     case 'Q':
  236.         end_pbq();
  237.     }
  238. }
  239.  
  240. /**************************************************************\
  241. *                                                              *
  242. * summarize_dir_info                                           *
  243. *                                                              *
  244. * This routine finds the directory entry for a given file,     *
  245. * if any.  It then summarizes the info to stdout.  It returns  *
  246. * the length of the file according to the directory.           *
  247. *                                                              *
  248. \**************************************************************/
  249.  
  250. unsigned long    summarize_dir_info(unsigned long file_number)
  251. {
  252. int            i;
  253. char            tstr[12];            // put the time string here
  254. struct tm     *tm_p;
  255. dir_entry    entry;
  256.  
  257. for (i=0; i<number_of_entries; i++)
  258.     if (findex[i].fileno == file_number)
  259.         break;
  260.  
  261. if (i >= number_of_entries)
  262.     return BAD_LENGTH;        /* No directory entry found; return bad length */
  263.  
  264. if (fseek(dirfile, findex[i].offset, SEEK_SET) != 0)
  265.     return BAD_LENGTH;        /* Can't seek.  Return bad length */
  266.  
  267. if (!fread((void *) &entry, sizeof entry, (size_t) 1, dirfile))
  268.     return BAD_LENGTH;        /* Can't read.  Return bad length */
  269.  
  270. tm_p = gmtime(&(entry.time));
  271. sprintf(tstr, "%02d/%02d %02d:%02d",
  272.             tm_p->tm_mon+1, tm_p->tm_mday, tm_p->tm_hour, tm_p->tm_min);
  273.  
  274. printf("         To: %8.8s\n"
  275.          "       From: %8.8s\n"
  276.          "       Time: %11s\n"
  277.          "      Title: %-39.39s\n",
  278.         entry.to, entry.from, tstr, entry.title);
  279.  
  280. if (entry.keywords[0] != '\0')        /* Don't display empty keywords field */
  281.     printf("   Keywords: %-19.19s\n", entry.keywords);
  282.  
  283. return entry.filesize;
  284. }
  285.  
  286. /*********************************************************\
  287. *                                                         *
  288. * summarize_hole_file                                     *
  289. *                                                         *
  290. * This routine reads the hole file for a given file, and  *
  291. * summarizes the statistics to stdout.                    *
  292. *                                                         *
  293. \*********************************************************/
  294.  
  295. void    summarize_hole_file(char *holname, unsigned long file_length)
  296. {
  297. FILE                *holfile;
  298. int                header_received;
  299. unsigned long    hlength;
  300. unsigned long    nholes, h;
  301. unsigned long    bytes_received = 0;
  302. unsigned long    bytes_missing = 0;
  303. unsigned long    last_address = 0;
  304. unsigned long    hfrom, hto;
  305.  
  306. if (((holfile = fopen(holname, "r")) == NULL)
  307.         ||
  308.      (fscanf(holfile,
  309.         "%d pfh header received\n"
  310.         "%ld pfh file length\n"
  311.         "%ld holes",
  312.         &header_received, &hlength, &nholes) != 3))
  313.     {
  314.     printf("Can't scan .HOL file!\n");
  315.     if (file_length != BAD_LENGTH)
  316.         printf("     Length: %ld\n", file_length);
  317.     if (holfile != NULL)
  318.         fclose(holfile);
  319.     return;
  320.     }
  321.  
  322. for (h=0; h<nholes; h++)
  323.     {
  324.     if (fscanf(holfile, " %ld, %ld", &hfrom, &hto) != 2)
  325.         {
  326.         printf("Can't scan .HOL file!\n");
  327.         if (file_length != BAD_LENGTH)
  328.             printf("     Length: %ld\n", file_length);
  329.         fclose(holfile);
  330.         return;
  331.         }
  332.     bytes_received += (hfrom - last_address);
  333.     if (hto != 0xFFFFFFFF)
  334.         bytes_missing += (hto + 1 - hfrom);
  335.     last_address = hto + 1;
  336.     }
  337.  
  338. if (header_received)
  339.     {
  340.     printf("     Length: %ld", hlength);
  341.     if (hlength != file_length)
  342.         printf("  (PG.DIR said %ld)", file_length);
  343.     printf("\n     Status: %d%% complete, %ld holes\n",
  344.                     (int)(((hlength-bytes_missing)*100)/hlength), nholes);
  345.     }
  346. else if (file_length != BAD_LENGTH)
  347.     {
  348.     bytes_missing += (file_length - hfrom);
  349.     printf("     Length: %ld\n", file_length);
  350.     printf("     Status: %d%% complete,  %ld holes\n",
  351.                     (int)(((file_length-bytes_missing)*100)/file_length), nholes);
  352.     }
  353. else
  354.     {
  355.     printf("     Status: %ld bytes received, %ld+ bytes in %ld holes.\n",
  356.                     bytes_received, bytes_missing, nholes);
  357.     }
  358.  
  359. }
  360.  
  361. void    hitanykey(void)
  362. {
  363. int    key;
  364.  
  365. printf("Hit any key to continue ...");
  366.  
  367. key = getch();
  368. if (key == '\0' || key == 0xE0)
  369.     getch();                        /* do the right thing with function keys */
  370. }
  371.  
  372. int get_option(char *opts)
  373. {
  374. int    key;
  375.  
  376. do {
  377.     key = getch();
  378.     if (key == 0 || key == 0xE0)
  379.         {
  380.         getch();
  381.         key = -1;
  382.         continue;
  383.         }
  384.     }
  385. while (strchr(opts, toupper(key)) == NULL);
  386.  
  387. return toupper(key);
  388. }
  389.  
  390. int delete_files(char *holname, char *actname)
  391. {
  392.  
  393. if (remove(holname))
  394.     {
  395.     printf("\nCouldn't delete hole file!\n");
  396.     hitanykey();
  397.     return 0;
  398.     }
  399.  
  400. if (remove(actname) && errno != ENOENT)
  401.     {
  402.     printf("\nCouldn't delete .ACT file!\n");
  403.     hitanykey();
  404.     return 0;
  405.     }
  406.  
  407. return 1;
  408. }
  409.